﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace MT.Common.Helpers
{
    public class PasswordHelper
    {
        public static char[] CreatePasswordHash(string password, int salt)
        {
            if (String.IsNullOrEmpty(password))
                throw new ArgumentNullException("password");

            byte[] saltBytes = ToByteArray(salt);

            byte[] passwordBytes = new byte[password.Length * sizeof(char) + saltBytes.Length];
            int passwordByteTail = 0;   // the next location to write to within the passwordBytes array

            // Copy the saltBytes into the beginning of the array
            for (int i = 0; i < saltBytes.Length; i++)
            {
                passwordBytes[passwordByteTail++] = saltBytes[i];
            }

            int temp;
            for (int i = 0; i < password.Length; i++)
            {
                temp = password[i];    // convert a single unicode char to a int
                passwordBytes[passwordByteTail++] = (byte)((temp & 0x0000FF00) >> 8);           // Copy out the individual char bytes
                passwordBytes[passwordByteTail++] = (byte)(temp & 0x000000FF);
            }

            byte[] rawHash;
            SHA256Managed sha = new SHA256Managed();

            rawHash = sha.ComputeHash(passwordBytes);

            // Convert the raw hash into a human-readable string
            System.Text.StringBuilder newHashString = new System.Text.StringBuilder();
            foreach (byte b in rawHash)
            {
                newHashString.Append(b.ToString("x2"));
            }

            // Copy the resulting hash into _passwordHash
            char[] passwordHash = new char[64];
            newHashString.CopyTo(0, passwordHash, 0, newHashString.Length);
            return passwordHash;
        }

        public static int CreatePasswordSalt()
        {
            RNGCryptoServiceProvider rand = new RNGCryptoServiceProvider();
            byte[] randBytes = new byte[4];
            rand.GetBytes(randBytes);

            return ToInt(randBytes);
        }

        private static byte[] ToByteArray(int i)
        {
            byte[] b = new byte[4];

            b[0] = (byte)((i & 0xFF000000) >> 24);
            b[1] = (byte)((i & 0x00FF0000) >> 16);
            b[2] = (byte)((i & 0x0000FF00) >> 8);
            b[3] = (byte)(i & 0x000000FF);

            return b;
        }

        private static int ToInt(byte[] b)
        {
            return b[0] * (256 * 256 * 256) + b[1] * (256 * 256) + b[2] * 256 + b[3];
        }

        public static bool ValidatePassword(string password, int passwordSalt, string passwordHash)
        {
            if (string.IsNullOrEmpty(passwordHash))
            {
                return false;
            }
            var passwordChars = Encoding.ASCII.GetChars(Encoding.ASCII.GetBytes(passwordHash));
            return ValidatePassword(password, passwordSalt, passwordChars);
        }

        public static bool ValidatePassword(string password, int passwordSalt, char[] passwordHash)
        {
            if (string.IsNullOrEmpty(password) || password.Length == 0)
                return false;

            // Check the provided password against that in the DB
            char[] userPasswordHash = CreatePasswordHash(password, passwordSalt);

            if (userPasswordHash.Length != passwordHash.Length)
                return false;

            for (int i = 0; i < userPasswordHash.Length; i++)
                if (userPasswordHash[i] != passwordHash[i])
                    return false;

            return true;
        }

        public static bool ContainChinese(string password)
        {
            return Encoding.Default.GetByteCount(password) > password.Length;
        }
    }
}